package com.turing.post.account.impl;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import com.turing.post.account.util.AccountBusiness;
import com.turing.post.account.util.AccountParam;
import com.turing.post.account.util.AccountSystemAddTradDetail;
import com.turing.post.account.util.AccountSystemAddTradDetailDao;
import com.turing.post.account.util.AccountSystemSpecialRegister;
import com.turing.post.account.util.AccountSystemSpecialRegisterDao;
import com.turing.post.account.util.AccountSystemTradDetail;
import com.turing.post.account.util.AccountSystemTradDetailDao;
import com.turing.post.account.util.DepositAccountParam;
import com.turing.post.account.util.DepositAccountResult;
import com.turing.post.account.util.MasterAccount;
import com.turing.post.account.util.MasterAccountBusiness;
import com.turing.post.account.util.MasterAccountDao;
import com.turing.post.account.util.MasterAccountTransferDetail;
import com.turing.post.account.util.MasterAccountTransferDetailDao;
import com.turing.post.account.util.OpenAccountParam;
import com.turing.post.account.util.OpenAccountResult;
import com.turing.post.account.util.SalesGroup;
import com.turing.post.account.util.SalesGroupDao;
import com.turing.post.account.util.SubAccount;
import com.turing.post.account.util.SubAccountBusiness;
import com.turing.post.account.util.SubAccountDao;
import com.turing.post.account.util.SubAccountDetail;
import com.turing.post.account.util.SubAccountDetailDao;
import com.turing.post.cardmanagement.util.ActivateCard;
import com.turing.post.cardmanagement.util.ActivateCardDao;
import com.turing.post.cardmanagement.util.MakeCardControl;
import com.turing.post.cardmanagement.util.MakeCardControlDao;
import com.turing.post.common.util.PCPSCommonDao;
import com.turing.post.tuxedo.util.TuxedoRespCode;
import com.turing.post.util.PCPSApplicationException;
import com.turing.post.util.PCPSUtil;

@Stateless(mappedName = "account.impl.AccountBusinessImpl")
@Remote
@Local
public class AccountBusinessImpl implements AccountBusiness {
	@PersistenceContext
	protected EntityManager _em;

	@EJB(mappedName = "account.impl.AccountBusinessImpl")
	private AccountBusiness accountBusinessImpl;

	@EJB(mappedName = "common.impl.PCPSCommonDaoImpl")
	private PCPSCommonDao pcpsCommonDaoImpl;

	@EJB(mappedName = "account.impl.MasterAccountDaoImpl")
	private MasterAccountDao masterAccountDaoImpl;

	@EJB(mappedName = "account.impl.SubAccountDaoImpl")
	private SubAccountDao subAccountDaoImpl;

	@EJB(mappedName = "account.impl.SalesGroupDaoImpl")
	private SalesGroupDao salesGroupDaoImpl;

	@EJB(mappedName = "account.impl.MasterAccountBusinessImpl")
	private MasterAccountBusiness masterAccountBusinessImpl;

	@EJB(mappedName = "account.impl.SubAccountBusinessImpl")
	private SubAccountBusiness subAccountBusinessImpl;

	@EJB(mappedName = "account.impl.AccountSystemTradDetailDaoImpl")
	private AccountSystemTradDetailDao accountSystemTradDetailDaoImpl;

	@EJB(mappedName = "account.impl.AccountSystemAddTradDetailDaoImpl")
	private AccountSystemAddTradDetailDao accountSystemAddTradDetailDaoImpl;

	@EJB(mappedName = "account.impl.SubAccountDetailDaoImpl")
	private SubAccountDetailDao subAccountDetailDaoImpl;

	@EJB(mappedName = "account.impl.AccountSystemSpecialRegisterDaoImpl")
	private AccountSystemSpecialRegisterDao accountSystemSpecialRegisterDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.ActivateCardDaoImpl")
	private ActivateCardDao activateCardDaoImpl;

	@EJB(mappedName = "account.impl.MasterAccountTransferDetailDaoImpl")
	private MasterAccountTransferDetailDao masterAccountTransferDetailDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.MakeCardControlDaoImpl")
	private MakeCardControlDao makeCardControlDaoImpl;

	/**
	 * 核心记帐返回参数
	 */
	class CoreAccountResult {
		/**
		 * 帐户子系统流水号
		 */
		public String accSeqNo = null;

		/**
		 * 核心记帐后按主帐户返回主帐号/余额信息
		 */
		Map<BigInteger, BigInteger> masterAccBal = null;
	}

	/**
	 * 主帐户状态
	 */
	class MasterAccountStatus {
		// 开户状态允许列表
		public Map<String, String> allowOpenStatus;

		// 销户状态允许列表
		public Map<String, String> allowCloseStatus;

		// 止付状态允许列表
		public Map<String, String> allowStopPayment;

		public MasterAccountStatus() {
			// 缺省构造函数
			allowOpenStatus = new HashMap<String, String>();
			allowOpenStatus.put(MasterAccount.MASTERACCOUNT_OPENSTATUS_NORMAL,
					"");

			allowCloseStatus = new HashMap<String, String>();
			allowCloseStatus.put(MasterAccount.MASTERACCOUNT_CLOSESTATUS_NONE,
					"");

			allowStopPayment = new HashMap<String, String>();
			allowStopPayment.put(MasterAccount.MASTERACCOUNT_STOPPAYMENT_NONE,
					"");
		}

		/**
		 * 正常记帐需要的额外状态
		 */
		public void setNormalStatus() {
			// 设置附加的销户状态允许列表
			allowCloseStatus.put(
					MasterAccount.MASTERACCOUNT_CLOSESTATUS_CLOSE_CANCELED, "");

			// 设置附加的止付状态允许列表
			allowStopPayment.put(MasterAccount.MASTERACCOUNT_STOPPAYMENT_FREE,
					"");
		}
	}

	/**
	 * 检查开户参数
	 * 
	 * @param oap
	 * @throws PCPSApplicationException
	 */
	private void checkOpenAccountParam(OpenAccountParam oap)
			throws PCPSApplicationException {

		if (oap == null || oap.initialAmount == null)
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"开户卡号" + oap.cardNo + "金额为NULL");

		if (oap.initialAmount.compareTo(BigInteger.ZERO) < 0)
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"开户卡号" + oap.cardNo + "金额" + oap.initialAmount + "非法");

		if (!PCPSUtil.isEmpty(oap.cardNo)) {
			/* 检查卡号的唯一性 */
		}
	}

	/**
	 * 检查一组开户参数
	 * 
	 * @param oap
	 * @throws PCPSApplicationException
	 */
	private void checkOpenAccountParam(ArrayList<OpenAccountParam> oapl)
			throws PCPSApplicationException {

		Hashtable<String, String> cardmap = new Hashtable<String, String>();

		// 对list中的所有成员遍历检查
		for (OpenAccountParam oap : oapl) {
			if (!PCPSUtil.isEmpty(oap.cardNo)) {
				if (cardmap.containsKey(oap.cardNo))
					throw new PCPSApplicationException(
							PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
							"", "开户卡号" + oap.cardNo + "不唯一");
				else
					cardmap.put(oap.cardNo, oap.cardNo);
			}
			checkOpenAccountParam(oap);
		}
	}

	/**
	 * 检查销售员组信息
	 * 
	 * @param salesList
	 * @throws PCPSApplicationException
	 */
	private void checkSalesGroup(ArrayList<SalesGroup> salesList)
			throws PCPSApplicationException {
		BigInteger allsum = BigInteger.ZERO;
		Hashtable<BigInteger, Integer> sales = new Hashtable<BigInteger, Integer>();

		for (SalesGroup sg : salesList) {
			if (sg.getSalesId() == null
					|| sales.containsKey(sg.getSalesId())
					|| sg.getDegreeOfcontribution() == null
					|| sg.getDegreeOfcontribution().compareTo(BigInteger.ZERO) <= 0)
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "销售员或贡献度非法!");
			sales.put(sg.getSalesId(), 0);
			allsum = allsum.add(sg.getDegreeOfcontribution());
		}

		/*
		 * if (!allsum.equals(BigInteger.valueOf(100))) throw new
		 * PCPSApplicationException(
		 * PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
		 * "销售员贡献度合计非法!");
		 */
	}

	/**
	 * 创建销售员组信息
	 * 
	 * @param salesList
	 * @throws PCPSApplicationException
	 */
	private BigInteger createSalesGroup_internal(ArrayList<SalesGroup> salesList)
			throws PCPSApplicationException {

		// 产生主键
		BigInteger salesGroupId = pcpsCommonDaoImpl.getUniqueIntegerKey();

		// 插入所有记录
		for (SalesGroup sg : salesList) {
			sg.setSalesGroupId(salesGroupId);
			salesGroupDaoImpl.insert(sg);
		}

		return salesGroupId;
	}

	private String getSalesGroupKey(SalesGroup sg) {
		StringBuilder sb = new StringBuilder();
		sb.append(sg.getSalesId());
		sb.append("_");
		sb.append(sg.getDegreeOfcontribution());
		return sb.toString();
	}

	/**
	 * 判断销售员组是否完全一致
	 * 
	 * @param sglist_s
	 * @param sglist_d
	 * @return
	 */
	private boolean isSalesGroupListIdentical(ArrayList<SalesGroup> sglist_s,
			ArrayList<SalesGroup> sglist_d) {
		if (sglist_s.size() != sglist_d.size())
			return false;

		Map<String, String> map = new HashMap<String, String>();

		for (SalesGroup sg : sglist_s) {
			String key = getSalesGroupKey(sg);
			map.put(key, key);
		}

		for (SalesGroup sg : sglist_d) {
			String key = getSalesGroupKey(sg);
			String nkey = map.remove(key);
			if (nkey == null)
				return false;
		}

		return map.size() == 0;
	}

	/**
	 * 创建销售员组信息,先查找
	 * 
	 * @param salesList
	 * @throws PCPSApplicationException
	 */
	private BigInteger createSalesGroup(ArrayList<SalesGroup> salesList)
			throws PCPSApplicationException {

		BigInteger hashval = BigInteger.ONE;

		// 20万以内的最大素数
		BigInteger prime = BigInteger.valueOf(199999);

		for (SalesGroup sg : salesList)
			hashval = hashval.multiply(sg.getSalesId()).multiply(
					sg.getDegreeOfcontribution()).mod(prime)
					.add(BigInteger.ONE);

		SalesGroup sgt = salesList.get(0);
		List<SalesGroup> sglist = salesGroupDaoImpl.getAllSalesGroupBySalesId(
				sgt.getSalesId(), hashval, sgt.getDegreeOfcontribution());
		if (sglist == null || sglist.size() < 1)
			return createSalesGroup_internal(salesList);

		// 将查询出来的列表按组ID分组
		Map<BigInteger, ArrayList<SalesGroup>> map = new HashMap<BigInteger, ArrayList<SalesGroup>>();

		for (SalesGroup sg : sglist) {
			ArrayList<SalesGroup> nsg = map.get(sg.getSalesGroupId());
			if (nsg == null) {
				nsg = new ArrayList<SalesGroup>();
				map.put(sg.getSalesGroupId(), nsg);
			}
			nsg.add(sg);
		}

		// 对每一个在map中的列表 ,比较与salesList是否完全相同
		for (Map.Entry<BigInteger, ArrayList<SalesGroup>> sgentry : map
				.entrySet()) {
			ArrayList<SalesGroup> sgm = sgentry.getValue();
			// 比较两个list是否相同
			if (isSalesGroupListIdentical(sgm, salesList))
				return sgm.get(0).getSalesGroupId();
		}

		// 必须要创建
		return createSalesGroup_internal(salesList);
	}

	/**
	 * 检查开户转入信息的合法性
	 * 
	 * @param openAccountParamList
	 * @param transferMap
	 * @throws PCPSApplicationException
	 */
	private void checkOpenTransferParam(
			ArrayList<OpenAccountParam> openAccountParamList,
			Map<String, Map<BigInteger, BigInteger>> transferMap)
			throws PCPSApplicationException {

		for (OpenAccountParam oap : openAccountParamList) {
			Map<BigInteger, BigInteger> map = transferMap.get(oap.cardNo);
			if (map == null || map.size() < 1)
				continue;
			BigInteger allamt = BigInteger.ZERO;
			for (Map.Entry<BigInteger, BigInteger> mentry : map.entrySet()) {
				BigInteger amt = mentry.getValue();
				if (amt == null || amt.compareTo(BigInteger.ZERO) < 0)
					throw new PCPSApplicationException(
							PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
							"", "批量开户转入资金明细错,卡号:" + oap.cardNo + ",银行帐户ID:"
									+ mentry.getKey() + ",金额:" + amt);
				allamt = allamt.add(amt);
			}
			if (allamt.compareTo(oap.initialAmount) > 0
					|| oap.initialAmount.compareTo(BigInteger.ZERO) <= 0)
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "批量开户转入资金明细错,卡号:" + oap.cardNo + ",资金:"
								+ oap.initialAmount + ", 转入合计:"
								+ allamt.toString());
		}
	}

	/**
	 * 创建主帐号转入明细
	 * 
	 * @param accSeqNo
	 *            流水号
	 * @param tranTime
	 *            记帐时间
	 * @param masaccno
	 *            主帐号
	 * @param ticketId
	 *            业务单ID
	 * @param transfermap
	 *            转账明细
	 */
	private void createTransferInDetail(String accSeqNo, Date tranTime,
			BigInteger masaccno, BigInteger ticketId,
			Map<BigInteger, BigInteger> transfermap)
			throws PCPSApplicationException {

		if (transfermap == null || transfermap.size() < 1)
			return;

		MasterAccountTransferDetail matd = null;

		for (Map.Entry<BigInteger, BigInteger> entry : transfermap.entrySet()) {
			matd = new MasterAccountTransferDetail();
			matd.setAccSeqNo(accSeqNo);
			matd.setMasterAccNo(masaccno);
			//System.out.println("============="+entry.getKey());
			BigInteger bankid = entry.getKey();
			// 如果bankid <= 0,则表示为现金方式
			if (bankid != null && BigInteger.ZERO.compareTo(bankid) >= 0)
				bankid = null;
			matd.setBankAccountId(bankid);
			matd.setTicketId(ticketId);
			matd.setTranTime(tranTime);
			matd.setTransferInAmount(entry.getValue());
			matd.setTransferOutAmount(BigInteger.ZERO);
			masterAccountTransferDetailDaoImpl.insert(matd);
		}
	}

	/**
	 * 按流水号取消主帐户转入明细
	 * 
	 * @param cancelSeqNo
	 * @param newSeqNo
	 * @param tranTime
	 * @throws PCPSApplicationException
	 */
	private void cancelTransferDetail(String cancelSeqNo, String newSeqNo,
			Date tranTime) throws PCPSApplicationException {
		List<MasterAccountTransferDetail> matdlist = masterAccountTransferDetailDaoImpl
				.getAllMasterAccountTransferDetailByAccSeqNo(cancelSeqNo);
		if (matdlist == null || matdlist.size() < 1)
			return;

		for (MasterAccountTransferDetail matd : matdlist) {
			MasterAccountTransferDetail matd_n = new MasterAccountTransferDetail();
			matd_n.setAccSeqNo(newSeqNo);
			matd_n.setMasterAccNo(matd.getMasterAccNo());
			matd_n.setBankAccountId(matd.getBankAccountId());
			matd_n.setTicketId(matd.getTicketId());
			matd_n.setTranTime(tranTime);
			matd_n.setTransferInAmount(BigInteger.ZERO.subtract(matd
					.getTransferInAmount()));
			matd_n.setTransferOutAmount(BigInteger.ZERO.subtract(matd
					.getTransferOutAmount()));
			masterAccountTransferDetailDaoImpl.insert(matd_n);
		}
	}

	/**
	 * 批量开户
	 * 
	 * @param issueCompanyNo
	 *            发卡商
	 * @param openBranchNo
	 *            开户机构号
	 * @param ticketId
	 *            相关业务单ID
	 * @param tranDate
	 *            帐务日期
	 * @param tranTime
	 *            记帐时间
	 * @param tranSeqNo
	 *            交易系统流水号
	 * @param operId
	 *            操作员ID
	 * @param summary
	 *            开户摘要
	 * @param openAccountParamList
	 *            每户的具体参数
	 * @param salesList
	 *            销售员列表
	 * @param transferMap
	 *            转账明细
	 * @return 批量开户返回结果
	 */
	public OpenAccountResult OpenAccount(String issueCompanyNo,
			String openBranchNo, BigInteger ticketId, Date tranDate,
			Date tranTime, String tranSeqNo, BigInteger operId, String summary,
			ArrayList<OpenAccountParam> openAccountParamList,
			ArrayList<SalesGroup> salesList,
			Map<String, Map<BigInteger, BigInteger>> transferMap)
			throws PCPSApplicationException {

		// PCPSUtil.Log(issueCompanyNo);
		// PCPSUtil.Log(openBranchNo);
		// PCPSUtil.Log(tranDate == null ? "null" : tranDate.toString());
		// PCPSUtil.Log(tranSeqNo);

		// 检查基本的入口参数
		if (PCPSUtil.isEmpty(issueCompanyNo) || PCPSUtil.isEmpty(openBranchNo)
				|| tranDate == null || PCPSUtil.isEmpty(tranSeqNo)
				|| openAccountParamList == null)
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"批量开户参数错");

		// 检查开户参数
		checkOpenAccountParam(openAccountParamList);

		BigInteger salesGroupId = null;

		// 记载销售员组信息
		if (salesList != null && salesList.size() > 0) {
			// 检查销售员组信息
			checkSalesGroup(salesList);
			// 创建销售员组信息
			salesGroupId = createSalesGroup(salesList);
		}

		// 检查转入信息的合法性
		if (transferMap != null && transferMap.size() >= 1)
			checkOpenTransferParam(openAccountParamList, transferMap);

		// 设置开户时间
		Date openTime = tranTime;

		OpenAccountResult oar = new OpenAccountResult();

		ArrayList<AccountParam> acclist = new ArrayList<AccountParam>();

		// 卡号与主帐号的对照
		Map<String, BigInteger> cardno2mas = new HashMap<String, BigInteger>();

		// 如果摘要没有指定
		if (PCPSUtil.isEmpty(summary))
			summary = "开户";

		// 循环开户
		for (OpenAccountParam oap : openAccountParamList) {
			AccountParam cap = new AccountParam();

			// 创建主帐户
			BigInteger masterAccNo = masterAccountBusinessImpl
					.createMasterAccount(issueCompanyNo, openTime, oap.cardNo,
							oap.ownerId, oap.remark);
			MasterAccount masacc = masterAccountDaoImpl
					.getMasterAccountByMasterAccNo(masterAccNo);
			if (masacc == null)
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐户开户失败!");
			// PCPSUtil.Log("MASTER:::" + masacc.getOpenTime().toString());

			// 登记卡号与主帐号的映射关系
			cardno2mas.put(oap.cardNo, masacc.getMasterAccNo());

			// 创建子帐户
			cap.subAccNo = subAccountBusinessImpl.createSubAccount(masterAccNo,
					openBranchNo, openTime, salesGroupId);
			/*
			 * PCPSUtil.Log("SUB:::" +
			 * subAccountDaoImpl.getSubAccountBySubAccNo(cap.subAccNo)
			 * .getOpenTime().toString());
			 * 
			 * PCPSUtil.Log("MASTER:" + masterAccNo.toString() + "/SUBACC:" +
			 * cap.subAccNo.toString());
			 */
			// 增加到返回列表
			oar.add(masterAccNo, oap.cardNo, cap.subAccNo);

			// 加入到记帐列表
			cap.creditAmount = oap.initialAmount;
			cap.debitAmount = BigInteger.ZERO;
			cap.tranType = AccountSystemAddTradDetail.TRANTYPE_OPEN;
			cap.summary = summary;

			acclist.add(cap);
		}

		// 开户记帐
		CoreAccountResult caresult = CoreAccount(tranDate, issueCompanyNo,
				openTime, tranSeqNo, operId, summary, null, null, null,
				acclist, new MasterAccountStatus());

		// 登记转入明细
		if (transferMap != null && transferMap.size() >= 1) {
			for (Map.Entry<String, BigInteger> c2mas : cardno2mas.entrySet())
				createTransferInDetail(caresult.accSeqNo, openTime, c2mas
						.getValue(), ticketId, transferMap.get(c2mas.getKey()));
		}

		// 准备开户返回信息
		oar.accSeqNo = caresult.accSeqNo;

		return oar;
	}

	/**
	 * 产生帐户子系统交易/特殊流水号
	 * 
	 * @param issueCompanyNo
	 * @param tranTime
	 * @return
	 */
	private String generateSeqNo(String issueCompanyNo, Date tranTime,
			String category) {
		BigInteger seqno = pcpsCommonDaoImpl.getAccountSubSystemSeqNo();
		seqno = seqno.mod(BigInteger.valueOf(1000000));

		return issueCompanyNo + category
				+ PCPSUtil.getStringYMDHMSPackedByDate(tranTime)
				+ String.format("%06d", seqno);
	}

	/**
	 * 产生帐户子系统交易流水号
	 * 
	 * @param issueCompanyNo
	 * @param tranTime
	 * @return
	 */
	private String generateAccSeqNo(String issueCompanyNo, Date tranTime) {
		return generateSeqNo(issueCompanyNo, tranTime, "ACC");
	}

	/**
	 * 产生帐户子系统特殊流水号
	 * 
	 * @param issueCompanyNo
	 * @param tranTime
	 * @return
	 */
	private String generateRegSeqNo(String issueCompanyNo, Date tranTime) {
		return generateSeqNo(issueCompanyNo, tranTime, "REG");
	}

	/**
	 * 根据交易类型返回取消业务的交易类型
	 * 
	 * @param tranType
	 * @throws PCPSApplicationException
	 */
	private String getCanceledTranType(String tranType)
			throws PCPSApplicationException {
		// 开户
		if (PCPSUtil.compareObject(tranType,
				AccountSystemAddTradDetail.TRANTYPE_OPEN))
			return AccountSystemAddTradDetail.TRANTYPE_OPEN_CANCELED;

		// 开户撤销
		if (PCPSUtil.compareObject(tranType,
				AccountSystemAddTradDetail.TRANTYPE_OPEN_CANCELED))
			return AccountSystemAddTradDetail.TRANTYPE_OPEN;

		// 消费
		if (PCPSUtil.compareObject(tranType,
				AccountSystemAddTradDetail.TRANTYPE_CONSUME))
			return AccountSystemAddTradDetail.TRANTYPE_CONSUME_CANCELED;

		// 消费撤销
		if (PCPSUtil.compareObject(tranType,
				AccountSystemAddTradDetail.TRANTYPE_CONSUME_CANCELED))
			return AccountSystemAddTradDetail.TRANTYPE_CONSUME;

		// 充值
		if (PCPSUtil.compareObject(tranType,
				AccountSystemAddTradDetail.TRANTYPE_DEPOSIT))
			return AccountSystemAddTradDetail.TRANTYPE_DEPOSIT_CANCELED;

		// 充值撤销
		if (PCPSUtil.compareObject(tranType,
				AccountSystemAddTradDetail.TRANTYPE_DEPOSIT_CANCELED))
			return AccountSystemAddTradDetail.TRANTYPE_DEPOSIT;

		// 赎回
		if (PCPSUtil.compareObject(tranType,
				AccountSystemAddTradDetail.TRANTYPE_REDEMP))
			return AccountSystemAddTradDetail.TRANTYPE_REDEMP_CANCELED;

		// 赎回撤销
		if (PCPSUtil.compareObject(tranType,
				AccountSystemAddTradDetail.TRANTYPE_REDEMP_CANCELED))
			return AccountSystemAddTradDetail.TRANTYPE_REDEMP;

		// 扣手续费
		if (PCPSUtil.compareObject(tranType,
				AccountSystemAddTradDetail.TRANTYPE_FEE))
			return AccountSystemAddTradDetail.RANTYPE_FEE_CANCELED;

		// 扣手续费撤销
		if (PCPSUtil.compareObject(tranType,
				AccountSystemAddTradDetail.RANTYPE_FEE_CANCELED))
			return AccountSystemAddTradDetail.TRANTYPE_FEE;

		// 调帐
		if (PCPSUtil.compareObject(tranType,
				AccountSystemAddTradDetail.TRANTYPE_ADJUST))
			return AccountSystemAddTradDetail.TRANTYPE_ADJUST;

		throw new PCPSApplicationException(
				PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
				"记帐类型" + tranType + "无效!");

	}

	/**
	 * 核心记帐流程 -- 内部调用
	 * 
	 * @param tranDate
	 *            记帐日期
	 * @param issueCompanyNo
	 *            发卡方
	 * @param tranTime
	 *            记帐时间
	 * @param tranType
	 *            记帐类型
	 * @param tranSeqNo
	 *            其他业务子系统流水号
	 * @param operId
	 *            操作员ID
	 * @param summary
	 *            业务摘要
	 * @param cancelAccSeqNo
	 *            被取消的帐务子系统流水号
	 * @param cancelTranDate
	 *            被取消的记帐日期
	 * @param cancelTranSeqNo
	 *            被取消的业务子系统流水号
	 * @param acclist
	 *            具体的记帐参数
	 * @param allowStatus
	 *            主帐户各状态的合法值
	 * @return 核心记帐返回参数
	 * @throws PCPSApplicationException
	 */
	private CoreAccountResult CoreAccount(Date tranDate, String issueCompanyNo,
			Date tranTime, String tranSeqNo, BigInteger operId, String summary,
			String cancelAccSeqNo, Date cancelTranDate, String cancelTranSeqNo,
			ArrayList<AccountParam> acclist, MasterAccountStatus allowStatus)
			throws PCPSApplicationException {

		CoreAccountResult caresult = new CoreAccountResult();

		// 确保记帐日期干净
		tranDate = PCPSUtil.getZeroedHMS(tranDate);

		// 产生流水号
		caresult.accSeqNo = generateAccSeqNo(issueCompanyNo, tranTime);

		AccountSystemAddTradDetail asatd = null;

		MasterAccount macc = null;
		BigInteger lastSubAccNo = null;
		SubAccount subacc = null;

		BigInteger totalCreditAmt = BigInteger.ZERO;
		BigInteger totalDebitAmt = BigInteger.ZERO;

		caresult.masterAccBal = new HashMap<BigInteger, BigInteger>();

		int i = 0;
		// 记附加子帐户明细
		for (AccountParam ap : acclist) {
			asatd = new AccountSystemAddTradDetail();

			// 检查tranType
			getCanceledTranType(ap.tranType);

			// 如果与上次的子帐户不一致
			if (!PCPSUtil.compareObject(lastSubAccNo, ap.subAccNo)) {
				subacc = subAccountDaoImpl.getSubAccountBySubAccNo(ap.subAccNo);
				if (subacc == null)
					throw new PCPSApplicationException(
							PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
							"", "子帐户无效" + ap.subAccNo.toString());
				macc = masterAccountDaoImpl
						.getMasterAccountByMasterAccNoForUpdate(subacc
								.getMasterAccNo());
				if (macc == null)
					throw new PCPSApplicationException(
							PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
							"", "子帐户的主帐户无效" + ap.subAccNo.toString());

				// 检查父帐户的帐户状态
				if (!macc.checkAccountStatus(allowStatus.allowOpenStatus,
						allowStatus.allowCloseStatus,
						allowStatus.allowStopPayment))
					throw new PCPSApplicationException(
							PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
							"", "主帐户" + macc.getMasterAccNo() + "状态不允许!");

				lastSubAccNo = ap.subAccNo;
			}

			// 全部转换为贷方发生额
			BigInteger amt = ap.creditAmount;
			amt = amt.subtract(ap.debitAmount);

			// 更新子帐户余额
			BigInteger subAccBalance = subAccountBusinessImpl.updateBalance(
					ap.subAccNo, amt, tranTime);

			// 更新主帐户余额
			BigInteger masAccBalance = masterAccountBusinessImpl.updateBalance(
					macc.getMasterAccNo(), amt, tranTime);

			// 同步更新卡余额
			if (!PCPSUtil.isEmpty(macc.getCardNo())) {
				ActivateCard ac = activateCardDaoImpl
						.getActivateCardByCardNoForUpdate(macc.getCardNo());
				ac.setBalance(masAccBalance);
				activateCardDaoImpl.update(ac);
			}

			// 先删除后增加
			caresult.masterAccBal.remove(macc.getMasterAccNo());
			caresult.masterAccBal.put(macc.getMasterAccNo(), masAccBalance);

			// 累计汇总额
			totalCreditAmt = totalCreditAmt.add(ap.creditAmount);
			totalDebitAmt = totalDebitAmt.add(ap.debitAmount);

			// 记载附加子帐户信息
			i++;
			Integer accsubseqno = new Integer(i);

			asatd.setAccSeqNo(caresult.accSeqNo);
			asatd.setAccSubSeqNo(accsubseqno);
			asatd.setIssueCompanyNo(issueCompanyNo);
			asatd.setTranDate(tranDate);
			asatd.setMasterAccNo(macc.getMasterAccNo());
			String cardNo = macc.getCardNo();
			if (cardNo != null) {
				asatd.setCardNo(cardNo);
				ActivateCard ac = activateCardDaoImpl
						.getActivateCardByCardNo(cardNo);
				if (ac != null)
					asatd.setCardClassicId(ac.getCardClassicId());
				else
					asatd.setCardClassicId(null);
			} else {
				asatd.setCardNo(null);
				asatd.setCardClassicId(null);
			}
			asatd.setSubAccNo(ap.subAccNo);
			asatd.setOpenBranchNo(subacc.getOpenBranchNo());
			asatd.setTranType(ap.tranType);
			asatd.setCreditAmount(ap.creditAmount);
			asatd.setDebitAmount(ap.debitAmount);
			asatd.setBalance(subAccBalance);

			// 2013.01.31 add
			asatd.setTranTime(tranTime);
			asatd.setMasBalance(masAccBalance);
			asatd.setRemark(summary);

			accountSystemAddTradDetailDaoImpl.insert(asatd);

			// 记载子帐户交易明细
			SubAccountDetail sad = new SubAccountDetail();
			sad.setSubAccNo(ap.subAccNo);
			sad.setTranDate(tranDate);
			sad.setTranTime(tranTime);
			sad.setAccSeqNo(caresult.accSeqNo);
			sad.setAccSubSeqNo(accsubseqno);
			sad.setCreditAmount(ap.creditAmount);
			sad.setDebitAmount(ap.debitAmount);
			sad.setBalance(subAccBalance);
			sad.setSummary(summary);

			subAccountDetailDaoImpl.insert(sad);
		}

		// 总分(主帐户 <--> 子帐户)核对检查
		for (Map.Entry<BigInteger, BigInteger> entry : caresult.masterAccBal
				.entrySet()) {
			BigInteger tabbal = subAccountDaoImpl
					.getAllSubAccountBalanceByMasterAccNo(entry.getKey());
			BigInteger accbal = entry.getValue();
			if (!PCPSUtil.compareObject(tabbal, accbal)) {
				PCPSUtil.Log(tabbal.toString() + " vs " + accbal.toString());
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "子帐户与主帐户余额总分不平" + entry.getKey());
			}
		}

		// 记交易流水
		AccountSystemTradDetail astd = new AccountSystemTradDetail();

		astd.setAccSeqNo(caresult.accSeqNo);
		astd.setTranDate(tranDate);
		astd.setIssueCompanyNo(issueCompanyNo);
		astd.setTranTime(tranTime);
		astd.setTranSeqNo(tranSeqNo);
		astd.setCreditAmount(totalCreditAmt);
		astd.setDebitAmount(totalDebitAmt);
		astd.setCancelAccSeqNo(cancelAccSeqNo);
		astd.setCancelTranDate(cancelTranDate);
		astd.setCancelTranSeqNo(cancelTranSeqNo);
		astd.setOperId(operId);
		astd.setSummary(summary);

		accountSystemTradDetailDaoImpl.insert(astd);

		// 返回核心记帐结果
		return caresult;
	}

	/**
	 * 无此流水
	 * 
	 * @param accSeqNo
	 * @throws PCPSApplicationException
	 */
	private void noSuchTradDetail(String accSeqNo)
			throws PCPSApplicationException {
		throw new PCPSApplicationException(
				PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
				"被撤销流水号不存在" + accSeqNo);
	}

	/**
	 * 核心记帐撤销流程 -- 内部调用
	 * 
	 * @param tranDate
	 *            交易日期
	 * @param issueCompanyNo
	 *            发卡方
	 * @param tranTime
	 *            记帐时间
	 * @param tranSeqNo
	 *            业务系统流水号
	 * @param origTranType
	 *            被撤销交易的交易类型
	 * @param tranType
	 *            本交易的交易类型
	 * @param cancelAccSeqNo
	 *            被撤销的帐户子系统流水号
	 * @param operId
	 *            操作员ID
	 * @param summary
	 *            摘要
	 * @param allowStatus
	 *            主帐户各状态的合法值
	 * @return 核心记帐撤销返回参数
	 * @throws PCPSApplicationException
	 */
	private CoreAccountResult CoreAccountCancel(Date tranDate,
			String issueCompanyNo, Date tranTime, String tranSeqNo,
			String cancelAccSeqNo, BigInteger operId, String summary,
			MasterAccountStatus allowStatus) throws PCPSApplicationException {

		// 标识该记录是否在历史表中
		boolean ishis = false;

		// 查找原始的被撤销流水
		AccountSystemTradDetail origtd = accountSystemTradDetailDaoImpl
				.getAccountSystemTradDetailByAccSeqNo(cancelAccSeqNo);
		if (origtd == null) {
			origtd = accountSystemTradDetailDaoImpl
					.getAccountSystemTradDetailByAccSeqNo(cancelAccSeqNo);
			if (origtd == null)
				noSuchTradDetail(cancelAccSeqNo);
			ishis = true;
		}

		// 检查是否是同一发卡商的流水
		if (!PCPSUtil.compareObject(issueCompanyNo, origtd.getIssueCompanyNo()))
			noSuchTradDetail(cancelAccSeqNo);

		// 检查是否已经被撤销
		if (!PCPSUtil.isEmpty(origtd.getCancelAccSeqNo())
				|| origtd.getCancelTranDate() != null
				|| !PCPSUtil.isEmpty(origtd.getCancelTranSeqNo()))
			noSuchTradDetail(cancelAccSeqNo);

		// 检索原始流水号所有的记帐信息
		List<AccountSystemAddTradDetail> allsubacc = accountSystemAddTradDetailDaoImpl
				.getAllAccountSystemAddTradDetailByAccSeqNo(cancelAccSeqNo);

		if (allsubacc == null || allsubacc.size() < 1)
			noSuchTradDetail(cancelAccSeqNo);

		// 准备撤销/冲正的记帐参数
		ArrayList<AccountParam> acclist = new ArrayList<AccountParam>();

		for (AccountSystemAddTradDetail asatd : allsubacc) {
			AccountParam cap = new AccountParam();
			cap.subAccNo = asatd.getSubAccNo();
			cap.creditAmount = BigInteger.ZERO
					.subtract(asatd.getCreditAmount());
			cap.debitAmount = BigInteger.ZERO.subtract(asatd.getDebitAmount());
			cap.tranType = getCanceledTranType(asatd.getTranType());
			cap.summary = "[撤销]" + asatd.getRemark();
			acclist.add(cap);
		}

		// 执行撤销记帐
		CoreAccountResult caresult = CoreAccount(tranDate, issueCompanyNo,
				tranTime, tranSeqNo, operId, summary, cancelAccSeqNo, origtd
						.getCancelTranDate(), origtd.getCancelTranSeqNo(),
				acclist, allowStatus);

		// 撤销主帐户转入明细
		cancelTransferDetail(cancelAccSeqNo, caresult.accSeqNo, tranTime);

		AccountSystemTradDetail astd = null;

		// 置原交易流水为撤销状态
		if (ishis) {
			astd = new AccountSystemTradDetail();
			astd.setAccSeqNo(cancelAccSeqNo);
			astd.setCancelAccSeqNo(caresult.accSeqNo);
			astd.setCancelTranDate(tranDate);
			astd.setCancelTranSeqNo(tranSeqNo);
			// 更新历史表
			int rows = accountSystemTradDetailDaoImpl
					.cancelAccountSystemHisTradDetail(astd);
			if (rows != 1)
				noSuchTradDetail(cancelAccSeqNo);
		} else {
			astd = accountSystemTradDetailDaoImpl
					.getAccountSystemTradDetailByAccSeqNo(cancelAccSeqNo);
			astd.setCancelAccSeqNo(caresult.accSeqNo);
			astd.setCancelTranDate(tranDate);
			astd.setCancelTranSeqNo(tranSeqNo);
			// 更新当前表
			accountSystemTradDetailDaoImpl.update(astd);
		}

		return caresult;
	}

	/**
	 * 重新记帐
	 * 
	 * @param issueCompanyNo
	 *            发卡方
	 * @param tranDate
	 *            交易日期
	 * @param tranTime
	 *            记帐时间
	 * @param tranSeqNo
	 *            交易流水
	 * @param origAccSeqNo
	 *            原始帐户子系统流水
	 * @param operId
	 *            操作员ID
	 * @param summary
	 *            摘要
	 * @return 记帐流水号
	 * @throws PCPSApplicationException
	 */
	public String redoAccount(String issueCompanyNo, Date tranDate,
			Date tranTime, String tranSeqNo, String origAccSeqNo,
			BigInteger operId, String summary) throws PCPSApplicationException {
		// 设置默认的状态列表
		MasterAccountStatus allowStatus = new MasterAccountStatus();

		// 设置附加的正常记帐额外状态允许列表
		allowStatus.setNormalStatus();

		// 查找原始的记帐流水
		AccountSystemTradDetail origtd = accountSystemTradDetailDaoImpl
				.getAccountSystemTradDetailByAccSeqNo(origAccSeqNo);
		if (origtd == null) {
			origtd = accountSystemTradDetailDaoImpl
					.getAccountSystemTradDetailByAccSeqNo(origAccSeqNo);
			if (origtd == null)
				noSuchTradDetail(origAccSeqNo);
		}

		// 被撤销的原始流水
		AccountSystemTradDetail otd = accountSystemTradDetailDaoImpl
				.getAccountSystemTradDetailByAccSeqNo(origtd
						.getCancelAccSeqNo());
		if (otd == null || PCPSUtil.isEmpty(otd.getCancelAccSeqNo()))
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"原始流水" + origAccSeqNo + "尚未撤销,不能重复记帐!");

		// 检查是否是同一发卡商的流水
		if (!PCPSUtil.compareObject(issueCompanyNo, origtd.getIssueCompanyNo()))
			noSuchTradDetail(origAccSeqNo);

		// 检索原始流水号所有的记帐信息
		List<AccountSystemAddTradDetail> allsubacc = accountSystemAddTradDetailDaoImpl
				.getAllAccountSystemAddTradDetailByAccSeqNo(origAccSeqNo);

		if (allsubacc == null || allsubacc.size() < 1)
			noSuchTradDetail(origAccSeqNo);

		// 准备重新记帐的参数
		ArrayList<AccountParam> acclist = new ArrayList<AccountParam>();

		for (AccountSystemAddTradDetail asatd : allsubacc) {
			AccountParam cap = new AccountParam();
			cap.subAccNo = asatd.getSubAccNo();
			cap.creditAmount = BigInteger.ZERO
					.subtract(asatd.getCreditAmount());
			cap.debitAmount = BigInteger.ZERO.subtract(asatd.getDebitAmount());
			cap.tranType = getCanceledTranType(asatd.getTranType());
			cap.summary = "[重新记帐]" + asatd.getRemark();
			acclist.add(cap);
		}

		// 执行重新记帐
		CoreAccountResult caresult = CoreAccount(tranDate, issueCompanyNo,
				tranTime, tranSeqNo, operId, summary, origAccSeqNo, origtd
						.getCancelTranDate(), origtd.getCancelTranSeqNo(),
				acclist, allowStatus);

		// 重做主帐户转入明细
		cancelTransferDetail(origAccSeqNo, caresult.accSeqNo, tranTime);

		// 置被撤销标记为NULL
		accountSystemTradDetailDaoImpl.resetCancelInf(otd.getAccSeqNo());

		return caresult.accSeqNo;
	}

	/**
	 * 开户撤销某主帐户
	 * 
	 * @param masaccno
	 * @throws PCPSApplicationException
	 */
	private void CancelOneMasterAccount(BigInteger masaccno)
			throws PCPSApplicationException {
		// 检索主帐户信息
		MasterAccount masacc = masterAccountDaoImpl
				.getMasterAccountByMasterAccNo(masaccno);
		if (masacc == null)
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"主帐户" + masaccno.toString() + "不存在");

		// 检查帐户余额必须为0
		if (!PCPSUtil.compareObject(masacc.getBalance(), BigInteger.ZERO))
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"主帐户" + masaccno.toString() + "不存在");

		// 置为开户取消状态
		masacc.setOpenStatus(MasterAccount.MASTERACCOUNT_OPENSTATUS_CANCELED);

		// 更新主帐户记录
		masterAccountDaoImpl.update(masacc);

		// 置卡号为NULL -- 通过SQL实现
		masterAccountDaoImpl.clearCardNo(masaccno);
	}

	/**
	 * 开户取消
	 * 
	 * @param issueCompanyNo
	 *            发卡商
	 * @param tranDate
	 *            当前帐务日期
	 * @param tranTime
	 *            记帐时间
	 * @param tranSeqNo
	 *            交易流水号
	 * @param cancelAccSeqNo
	 *            被取消的帐户子系统流水号
	 * @param operId
	 *            当前操作员ID
	 * @param summary
	 *            取消摘要
	 * @return 帐户子系统新流水号
	 * @throws PCPSApplicationException
	 */
	public String OpenAccountCancel(String issueCompanyNo, Date tranDate,
			Date tranTime, String tranSeqNo, String cancelAccSeqNo,
			BigInteger operId, String summary) throws PCPSApplicationException {

		// 设置默认的状态列表
		MasterAccountStatus allowStatus = new MasterAccountStatus();

		// 开户取消记帐
		CoreAccountResult caresult = CoreAccountCancel(tranDate,
				issueCompanyNo, tranTime, tranSeqNo, cancelAccSeqNo, operId,
				summary, allowStatus);

		// 设置所有主帐户开户状态为开户撤销
		for (Map.Entry<BigInteger, BigInteger> entry : caresult.masterAccBal
				.entrySet())
			CancelOneMasterAccount(entry.getKey());

		return caresult.accSeqNo;
	}

	/**
	 * 无此子帐户
	 * 
	 * @param subAccNo
	 * @throws PCPSApplicationException
	 */
	private void noSuchSubAccount(BigInteger subAccNo)
			throws PCPSApplicationException {
		if (subAccNo == null)
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"子帐户为NULL");
		throw new PCPSApplicationException(
				PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
				"子帐户" + subAccNo.toString() + "不存在");
	}

	/**
	 * 检查记帐参数
	 * 
	 * @param issueCompanyNo
	 *            发卡方
	 * @param accountParamList
	 *            记帐参数
	 * @throws PCPSApplicationException
	 */
	private void checkAccountParam(String issueCompanyNo,
			ArrayList<AccountParam> accountParamList,
			MasterAccountStatus allowStatus) throws PCPSApplicationException {
		if (accountParamList == null || accountParamList.size() < 1)
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"记帐参数错");

		Map<BigInteger, BigInteger> allmaster = new HashMap<BigInteger, BigInteger>();

		for (AccountParam ap : accountParamList) {
			if (ap.creditAmount == null || ap.debitAmount == null)
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "记帐金额非法");
			if (ap.creditAmount.compareTo(BigInteger.ZERO) == 0
					&& ap.debitAmount.compareTo(BigInteger.ZERO) == 0)
				continue;

			// 检查子帐户的存在性
			SubAccount sac = subAccountDaoImpl
					.getSubAccountBySubAccNoForUpdate(ap.subAccNo);
			if (sac == null || sac.getMasterAccNo() == null)
				noSuchSubAccount(ap.subAccNo);

			if (!allmaster.containsKey(sac.getMasterAccNo()))
				allmaster.put(sac.getMasterAccNo(), sac.getMasterAccNo());
		}

		// 必须有至少一个主帐户
		if (allmaster.size() < 1)
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"记帐参数错");

		// 检查所有主帐户状态
		for (Map.Entry<BigInteger, BigInteger> entry : allmaster.entrySet()) {
			MasterAccount masacc = masterAccountDaoImpl
					.getMasterAccountByMasterAccNoForUpdate(entry.getKey());
			if (masacc == null || masacc.getIssueCompanyNo() == null)
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐号" + entry.getKey() + "不存在");
			// 检查状态
			if (!masacc.checkAccountStatus(allowStatus.allowOpenStatus,
					allowStatus.allowCloseStatus, allowStatus.allowStopPayment))
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐号" + entry.getKey() + "状态不允许");

			// 检查主帐户所属的发卡方与当前记帐的发卡方是否一致
			if (!PCPSUtil.compareObject(masacc.getIssueCompanyNo(),
					issueCompanyNo))
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐号" + entry.getKey() + "归属错");
		}
	}

	/**
	 * 记帐
	 * 
	 * @param issueCompanyNo
	 *            发卡方
	 * @param tranDate
	 *            交易日期
	 * @param tranTime
	 *            记帐时间
	 * @param tranSeqNo
	 *            交易流水
	 * @param operId
	 *            操作员ID
	 * @param summary
	 *            摘要
	 * @param accountParamList
	 *            具体的记帐参数
	 * @return 记帐流水号
	 * @throws PCPSApplicationException
	 */
	public String Account(String issueCompanyNo, Date tranDate, Date tranTime,
			String tranSeqNo, BigInteger operId, String summary,
			ArrayList<AccountParam> accountParamList)
			throws PCPSApplicationException {

		// 设置默认的状态列表
		MasterAccountStatus allowStatus = new MasterAccountStatus();

		// 设置附加的正常记帐额外状态允许列表
		allowStatus.setNormalStatus();

		// 记帐参数检查
		checkAccountParam(issueCompanyNo, accountParamList, allowStatus);

		// 记帐
		CoreAccountResult caresult = CoreAccount(tranDate, issueCompanyNo,
				tranTime, tranSeqNo, operId, summary, null, null, null,
				accountParamList, allowStatus);

		return caresult.accSeqNo;
	}

	/**
	 * 撤销记帐
	 * 
	 * @param issueCompanyNo
	 *            发卡方
	 * @param tranDate
	 *            交易日期
	 * @param tranTime
	 *            记帐时间
	 * @param tranSeqNo
	 *            交易流水
	 * @param cancelAccSeqNo
	 *            被撤销帐户子系统流水
	 * @param operId
	 *            操作员ID
	 * @param summary
	 *            摘要
	 * @return 记帐流水号
	 * @throws PCPSApplicationException
	 */
	public String AccountCancel(String issueCompanyNo, Date tranDate,
			Date tranTime, String tranSeqNo, String cancelAccSeqNo,
			BigInteger operId, String summary) throws PCPSApplicationException {
		// 设置默认的状态列表
		MasterAccountStatus allowStatus = new MasterAccountStatus();

		// 设置附加的正常记帐额外状态允许列表
		allowStatus.setNormalStatus();

		// 撤销记帐
		CoreAccountResult caresult = CoreAccountCancel(tranDate,
				issueCompanyNo, tranTime, tranSeqNo, cancelAccSeqNo, operId,
				summary, allowStatus);

		return caresult.accSeqNo;
	}

	/**
	 * 检查充值参数
	 * 
	 * @param dap
	 * @throws PCPSApplicationException
	 */
	private void checkDepositAccountParam(DepositAccountParam dap,
			String issueCompanyNo) throws PCPSApplicationException {

		if (dap == null || dap.masterAccNo == null)
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"充值参数错!");

		if (dap.depositAmount == null)
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"主帐号" + dap.masterAccNo.toString() + "金额为NULL");

		if (dap.depositAmount.compareTo(BigInteger.ZERO) < 0)
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"主帐号" + dap.masterAccNo.toString() + "金额"
							+ dap.depositAmount.toString() + "非法");

		MasterAccount masacc = masterAccountDaoImpl
				.getMasterAccountByMasterAccNoForUpdate(dap.masterAccNo);
		if (masacc == null)
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"主帐号" + dap.masterAccNo.toString() + "不存在");

		if (!PCPSUtil.compareObject(issueCompanyNo, masacc.getIssueCompanyNo()))
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"主帐号" + dap.masterAccNo.toString() + "归属错");
	}

	/**
	 * 检查一组充值参数
	 * 
	 * @param oap
	 * @throws PCPSApplicationException
	 */
	private void checkDepositAccountParam(ArrayList<DepositAccountParam> dapl,
			String issueCompanyNo) throws PCPSApplicationException {

		// 对list中的所有成员遍历检查
		for (DepositAccountParam dap : dapl)
			checkDepositAccountParam(dap, issueCompanyNo);
	}

	/**
	 * 检查充值转入信息的合法性
	 * 
	 * @param openAccountParamList
	 * @param transferMap
	 * @throws PCPSApplicationException
	 */
	private void checkDepositTransferParam(
			ArrayList<DepositAccountParam> depositAccountParamList,
			Map<BigInteger, Map<BigInteger, BigInteger>> transferMap)
			throws PCPSApplicationException {

		for (DepositAccountParam oap : depositAccountParamList) {
			Map<BigInteger, BigInteger> map = transferMap.get(oap.masterAccNo);
			if (map == null || map.size() < 1)
				continue;
			BigInteger allamt = BigInteger.ZERO;
			for (Map.Entry<BigInteger, BigInteger> mentry : map.entrySet()) {
				BigInteger amt = mentry.getValue();
				if (amt == null || amt.compareTo(BigInteger.ZERO) < 0)
					throw new PCPSApplicationException(
							PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
							"", "批量充值转入资金明细错,主帐号:" + oap.masterAccNo
									+ ",银行帐户ID:" + mentry.getKey() + ",金额:"
									+ amt);
				allamt = allamt.add(amt);
			}
			if (allamt.compareTo(oap.depositAmount) > 0
					|| oap.depositAmount.compareTo(BigInteger.ZERO) <= 0)
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "批量充值转入资金明细错,主帐号:" + oap.masterAccNo + ",资金:"
								+ oap.depositAmount);
		}
	}

	/**
	 * 查找一个适合的子帐户用来充值,免除开立子帐户
	 * 
	 * @param masterAccNo
	 *            主帐号
	 * @param saleBranchNo
	 *            开户机构号
	 * @param salesGroupId
	 *            销售员组ID
	 * @return
	 */
	private BigInteger getSuitSubAccNo(BigInteger masterAccNo,
			String saleBranchNo, BigInteger salesGroupId) {
		List<SubAccount> salist = subAccountDaoImpl
				.getSubAccountListByMasterAccNo(masterAccNo);

		// 2013.07.12 modify by yxb 始终返回第1个子帐户
		return salist.get(0).getSubAccNo();

		// 适合充当充值记帐子帐户的条件是
		// 
		// 1. 开户的销售机构一致
		// 2. 销售员组相同

		/*
		 * for (SubAccount sa : salist) { if
		 * (!PCPSUtil.compareObject(sa.getOpenBranchNo(), saleBranchNo))
		 * continue; if (!PCPSUtil.compareObject(sa.getSalesGroupId(),
		 * salesGroupId)) continue; return sa.getSubAccNo(); }
		 * 
		 * return null;
		 */
	}

	/**
	 * 充值
	 * 
	 * @param issueCompanyNo
	 *            发卡商
	 * @param openBranchNo
	 *            开户机构号
	 * @param ticketId
	 *            相关业务单ID
	 * @param tranDate
	 *            帐务日期
	 * @param tranTime
	 *            记帐时间
	 * @param tranSeqNo
	 *            交易系统流水号
	 * @param operId
	 *            操作员ID
	 * @param summary
	 *            充值摘要
	 * @param depositAccountParamList
	 *            每户的具体参数
	 * @param salesList
	 *            销售员列表
	 * @param transferMap
	 *            转账明细
	 * @return 批量充值返回结果
	 */
	public DepositAccountResult DepositAccount(String issueCompanyNo,
			String openBranchNo, BigInteger ticketId, Date tranDate,
			Date tranTime, String tranSeqNo, BigInteger operId, String summary,
			ArrayList<DepositAccountParam> depositAccountParamList,
			ArrayList<SalesGroup> salesList,
			Map<BigInteger, Map<BigInteger, BigInteger>> transferMap)
			throws PCPSApplicationException {

		// 检查基本的入口参数
		if (PCPSUtil.isEmpty(issueCompanyNo) || PCPSUtil.isEmpty(openBranchNo)
				|| tranDate == null || PCPSUtil.isEmpty(tranSeqNo)
				|| depositAccountParamList == null
				|| depositAccountParamList.size() < 1)
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
					TuxedoRespCode.RC_PARAMETER, "充值参数错");

		// 检查充值参数
		checkDepositAccountParam(depositAccountParamList, issueCompanyNo);

		// 检查转入明细
		if (transferMap != null && transferMap.size() >= 1)
			checkDepositTransferParam(depositAccountParamList, transferMap);

		BigInteger salesGroupId = null;

		// 记载销售员组信息
		if (salesList != null && salesList.size() > 0) {
			// 检查销售员组信息
			checkSalesGroup(salesList);
			// 创建销售员组信息
			salesGroupId = createSalesGroup(salesList);
		}

		// 如果摘要没有指定
		if (PCPSUtil.isEmpty(summary))
			summary = "充值";

		// 充值返回结果
		DepositAccountResult dar = new DepositAccountResult();

		ArrayList<AccountParam> acclist = new ArrayList<AccountParam>();

		// 循环开户
		for (DepositAccountParam oap : depositAccountParamList) {
			AccountParam cap = new AccountParam();

			cap.subAccNo = null;

			// 先查找一个适宜的子帐户
			cap.subAccNo = getSuitSubAccNo(oap.masterAccNo, openBranchNo,
					salesGroupId);

			// 创建子帐户
			if (cap.subAccNo == null)
				cap.subAccNo = subAccountBusinessImpl.createSubAccount(
						oap.masterAccNo, openBranchNo, tranTime, salesGroupId);

			// 增加到返回列表
			dar.add(oap.masterAccNo, cap.subAccNo);

			// 贷方记帐
			cap.creditAmount = oap.depositAmount;
			cap.debitAmount = BigInteger.ZERO;
			cap.tranType = AccountSystemAddTradDetail.TRANTYPE_DEPOSIT;
			cap.summary = "[充值]" + summary;
			acclist.add(cap);
		}

		// 设置默认的状态列表
		MasterAccountStatus allowStatus = new MasterAccountStatus();

		// 设置附加的正常记帐额外状态允许列表
		allowStatus.setNormalStatus();

		// 充值记帐
		CoreAccountResult caresult = CoreAccount(tranDate, issueCompanyNo,
				tranTime, tranSeqNo, operId, summary, null, null, null,
				acclist, allowStatus);

		// 登记转入明细
		if (transferMap != null && transferMap.size() >= 1) {
			for (DepositAccountParam oap : depositAccountParamList)
				createTransferInDetail(caresult.accSeqNo, tranTime,
						oap.masterAccNo, ticketId, transferMap
								.get(oap.masterAccNo));
		}

		// 记帐流水号
		dar.accSeqNo = caresult.accSeqNo;

		return dar;
	}

	/**
	 * 获取有效的主帐户列表
	 * 
	 * @param issueCompanyNo
	 *            发卡商
	 * @param masAccNoList
	 *            主帐号列表
	 * @return 处理流水号
	 */
	private Map<BigInteger, MasterAccount> getValidMasterAccounts(
			String issueCompanyNo, Map<BigInteger, BigInteger> masAccNoMap)
			throws PCPSApplicationException {

		Map<BigInteger, MasterAccount> allmas = new HashMap<BigInteger, MasterAccount>();

		for (Map.Entry<BigInteger, BigInteger> masacc_entry : masAccNoMap
				.entrySet()) {
			BigInteger masacc = masacc_entry.getKey();
			if (masacc == null)
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐号为NULL");

			MasterAccount macc = masterAccountDaoImpl
					.getMasterAccountByMasterAccNoForUpdate(masacc);
			if (macc == null)
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐号" + masacc.toString() + "不存在");

			if (!PCPSUtil.compareObject(issueCompanyNo, macc
					.getIssueCompanyNo()))
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐号" + masacc.toString() + "归属不正确");

			// 检查开户状态 & 销户状态
			if (macc.alreadyClosed())
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐号" + masacc.toString() + "已关闭");

			if (allmas.containsKey(masacc))
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐号" + masacc.toString() + "重复");

			// 加入到列表
			allmas.put(masacc, macc);
		}

		return allmas;
	}

	/**
	 * 冻结状态操作
	 * 
	 * @param issueCompanyNo
	 *            发卡商
	 * @param operId
	 *            操作员ID
	 * @param summary
	 *            冻结/解冻结摘要
	 * @param masAccNoMap
	 *            主帐号列表
	 * @param isfree
	 *            是否解除
	 * @return 处理流水号
	 */
	public String FreezeAccount(String issueCompanyNo, BigInteger operId,
			String summary, Map<BigInteger, BigInteger> masAccNoMap,
			boolean isfree) throws PCPSApplicationException {

		// 获取有效的主帐户列表
		Map<BigInteger, MasterAccount> allmas = getValidMasterAccounts(
				issueCompanyNo, masAccNoMap);

		// 交易时间
		Date tranTime = pcpsCommonDaoImpl.getDatabaseSysTime();

		// 生成业务受理流水号
		String regSeqNo = generateRegSeqNo(issueCompanyNo, tranTime);

		String newFreezeStatus = isfree ? MasterAccount.MASTERACCOUNT_FREEZE_FREE
				: MasterAccount.MASTERACCOUNT_FREEZE_ALREADY;

		String tranType = isfree ? AccountSystemSpecialRegister.ACCOUNTSYSTEMSPECIALREGISTER_FREEZE_FREE
				: AccountSystemSpecialRegister.ACCOUNTSYSTEMSPECIALREGISTER_FREEZE;

		// 循环处理
		for (Map.Entry<BigInteger, MasterAccount> entry : allmas.entrySet()) {
			MasterAccount macc = entry.getValue();
			boolean isalready = PCPSUtil.compareObject(macc.getFreeze(),
					MasterAccount.MASTERACCOUNT_FREEZE_ALREADY);
			BigInteger freezeAmt = masAccNoMap.get(entry.getKey());
			if (!isfree
					&& (freezeAmt == null || freezeAmt
							.compareTo(BigInteger.ZERO) <= 0))
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐号" + macc.getMasterAccNo() + "冻结金额非法!");
			if (isfree && !isalready)
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐号" + macc.getMasterAccNo() + "未冻结,不能解冻结!");
			else if (!isfree && isalready)
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐号" + macc.getMasterAccNo() + "已冻结,不能再次冻结!");

			// 设置冻结状态
			macc.setFreeze(newFreezeStatus);

			// 解冻结置0,冻结设置
			if (isfree)
				macc.setFreezeAmount(BigInteger.ZERO);
			else
				macc.setFreezeAmount(freezeAmt);

			// 更新主帐户记录
			masterAccountDaoImpl.update(macc);

			// 记载特殊流水
			AccountSystemSpecialRegister assr = new AccountSystemSpecialRegister();

			assr.setRegSeqNo(regSeqNo);
			assr.setMasterAccNo(macc.getMasterAccNo());
			assr.setCardNo(macc.getCardNo());
			assr.setBalance(macc.getBalance());
			assr.setIssueCompanyNo(macc.getIssueCompanyNo());
			assr.setTranTime(tranTime);
			assr.setTranType(tranType);
			assr.setOperId(operId);
			assr.setRemark(summary);

			accountSystemSpecialRegisterDaoImpl.insert(assr);

		}

		return regSeqNo;
	}

	/**
	 * 止付状态操作
	 * 
	 * @param issueCompanyNo
	 *            发卡商
	 * @param operId
	 *            操作员ID
	 * @param summary
	 *            止付/解止付摘要
	 * @param masAccNoMap
	 *            主帐号列表
	 * @param isfree
	 *            是否解除
	 * @return 处理流水号
	 */
	public String StopPaymentAccount(String issueCompanyNo, BigInteger operId,
			String summary, Map<BigInteger, BigInteger> masAccNoMap,
			boolean isfree) throws PCPSApplicationException {
		// 获取有效的主帐户列表
		Map<BigInteger, MasterAccount> allmas = getValidMasterAccounts(
				issueCompanyNo, masAccNoMap);

		// 交易时间
		Date tranTime = pcpsCommonDaoImpl.getDatabaseSysTime();

		// 生成业务受理流水号
		String regSeqNo = generateRegSeqNo(issueCompanyNo, tranTime);

		String newStopPaymentStatus = isfree ? MasterAccount.MASTERACCOUNT_STOPPAYMENT_FREE
				: MasterAccount.MASTERACCOUNT_STOPPAYMENT_ALREADY;

		String tranType = isfree ? AccountSystemSpecialRegister.ACCOUNTSYSTEMSPECIALREGISTER_STOPPAYMENT_FREE
				: AccountSystemSpecialRegister.ACCOUNTSYSTEMSPECIALREGISTER_STOPPAYMENT;

		// 循环处理
		for (Map.Entry<BigInteger, MasterAccount> entry : allmas.entrySet()) {
			MasterAccount macc = entry.getValue();
			boolean isalready = PCPSUtil.compareObject(macc.getStopPayment(),
					MasterAccount.MASTERACCOUNT_STOPPAYMENT_ALREADY);
			if (isfree && !isalready)
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐号" + macc.toString() + "未止付,不能解止付!");
			else if (!isfree && isalready)
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐号" + macc.toString() + "已止付,不能再次止付!");

			// 设置止付状态
			macc.setStopPayment(newStopPaymentStatus);

			// 更新主帐户记录
			masterAccountDaoImpl.update(macc);

			// 记载特殊流水
			AccountSystemSpecialRegister assr = new AccountSystemSpecialRegister();

			assr.setRegSeqNo(regSeqNo);
			assr.setMasterAccNo(macc.getMasterAccNo());
			assr.setCardNo(macc.getCardNo());
			assr.setBalance(macc.getBalance());
			assr.setIssueCompanyNo(macc.getIssueCompanyNo());
			assr.setTranTime(tranTime);
			assr.setTranType(tranType);
			assr.setOperId(operId);
			assr.setRemark(summary);

			accountSystemSpecialRegisterDaoImpl.insert(assr);

		}

		return regSeqNo;
	}

	@Override
	public OpenAccountResult OpenAppManageAccount(String issueCompanyNo,
			String openBranchNo, BigInteger ticketId, Date tranDate,
			Date tranTime, String tranSeqNo, BigInteger operId, String summary,
			ArrayList<OpenAccountParam> openAccountParamList)
			throws PCPSApplicationException {
		PCPSUtil.Log(issueCompanyNo);
		PCPSUtil.Log(openBranchNo);
		PCPSUtil.Log(tranDate == null ? "null" : tranDate.toString());
		PCPSUtil.Log(tranSeqNo);

		// 检查基本的入口参数
		if (PCPSUtil.isEmpty(issueCompanyNo) || PCPSUtil.isEmpty(openBranchNo)
				|| tranDate == null || PCPSUtil.isEmpty(tranSeqNo)
				|| openAccountParamList == null)
			throw new PCPSApplicationException(
					PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
					"批量开户参数错");

		// 检查开户参数
		// checkOpenAccountParam(openAccountParamList);

		// 应用顺序号
		String appSeqNo = null;

		// 设置开户时间
		Date openTime = tranTime;

		OpenAccountResult oar = new OpenAccountResult();

		ArrayList<AccountParam> acclist = new ArrayList<AccountParam>();

		// 卡号与主帐号的对照
		Map<String, BigInteger> cardno2mas = new HashMap<String, BigInteger>();

		// 如果摘要没有指定
		if (PCPSUtil.isEmpty(summary))
			summary = "开户";

		// 循环开户
		for (OpenAccountParam oap : openAccountParamList) {
			AccountParam cap = new AccountParam();

			// 创建主帐户
			BigInteger masterAccNo = masterAccountBusinessImpl
					.createMasterAccount(issueCompanyNo, openTime, oap.cardNo,
							oap.ownerId, oap.remark);
			MasterAccount masacc = masterAccountDaoImpl
					.getMasterAccountByMasterAccNo(masterAccNo);
			if (masacc == null)
				throw new PCPSApplicationException(
						PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "主帐户开户失败!");
			// PCPSUtil.Log("MASTER:::" + masacc.getOpenTime().toString());

			// 登记卡号与主帐号的映射关系
			cardno2mas.put(oap.cardNo, masacc.getMasterAccNo());

			// 创建子帐户
			cap.subAccNo = subAccountBusinessImpl.createAppManageSubAccount(
					masterAccNo, openBranchNo, openTime, appSeqNo);
			/*
			 * PCPSUtil.Log("SUB:::" +
			 * subAccountDaoImpl.getSubAccountBySubAccNo(cap.subAccNo)
			 * .getOpenTime().toString());
			 * 
			 * PCPSUtil.Log("MASTER:" + masterAccNo.toString() + "/SUBACC:" +
			 * cap.subAccNo.toString());
			 */
			// 增加到返回列表
			oar.add(masterAccNo, oap.cardNo, cap.subAccNo);

			// 加入到记帐列表
			cap.creditAmount = oap.initialAmount;
			cap.debitAmount = BigInteger.ZERO;
			cap.tranType = AccountSystemAddTradDetail.TRANTYPE_OPEN;
			cap.summary = summary;

			acclist.add(cap);
		}

		// 开户记帐
		CoreAccountResult caresult = CoreAccount(tranDate, issueCompanyNo,
				openTime, tranSeqNo, operId, summary, null, null, null,
				acclist, new MasterAccountStatus());

		// 准备开户返回信息
		oar.accSeqNo = caresult.accSeqNo;

		return oar;
	}

	// 以下为产生压力测试程序代码
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public void generateAccDetail(String issueCompanyNo, BigInteger subaccno,
			Date tranDate, Date tranTime) throws PCPSApplicationException {
		ArrayList<AccountParam> accountParamList = new ArrayList<AccountParam>();
		AccountParam ap = new AccountParam();
		ap.subAccNo = subaccno;
		ap.creditAmount = BigInteger.ZERO;
		ap.debitAmount = BigInteger.ONE;
		ap.summary = "消费";
		ap.tranType = AccountSystemAddTradDetail.TRANTYPE_CONSUME;
		accountParamList.add(ap);
		accountBusinessImpl.Account(issueCompanyNo, tranDate, tranTime,
				PCPSUtil.getStringYMDHMSPackedByDate(tranTime), null, "消费",
				accountParamList);
	}

	public void genAccDetail(String issueCompanyNo, BigInteger subaccno,
			String startDate, String endDate) {
		SubAccount sac = subAccountDaoImpl.getSubAccountBySubAccNo(subaccno);
		if (sac == null
				|| BigInteger.valueOf(60).compareTo(sac.getBalance()) > 0)
			return;
		Date sd = PCPSUtil.getDateYMDByString(startDate);
		Date ed = PCPSUtil.getDateYMDByString(endDate);

		MasterAccount mas = masterAccountDaoImpl
				.getMasterAccountByMasterAccNo(sac.getMasterAccNo());
		if (mas == null)
			return;

		ActivateCard ac = activateCardDaoImpl.getActivateCardByCardNo(mas
				.getCardNo());
		MakeCardControl mcc = makeCardControlDaoImpl
				.getMakeCardControlByBatchNo(ac.getBatchNo());
		if (!PCPSUtil.compareObject(mcc.getIssueCompanyNo(), issueCompanyNo))
			return;

		for (int i = 0; i < 60; i++) {
			java.util.Calendar cal = java.util.Calendar.getInstance();
			cal.setTime(PCPSUtil.getZeroedHMS(sd));
			java.util.Random random = new java.util.Random(31);
			cal.add(java.util.Calendar.DAY_OF_MONTH,
					1 + (random.nextInt() % 11));
			while (cal.getTime().compareTo(sd) < 0)
				cal.add(java.util.Calendar.DAY_OF_MONTH, 1);
			sd = cal.getTime();
			if (sd.compareTo(ed) > 0)
				break;
			cal.set(java.util.Calendar.HOUR_OF_DAY, (random.nextInt() % 23));
			cal.set(java.util.Calendar.MINUTE, (random.nextInt() % 60));
			cal.set(java.util.Calendar.SECOND, (random.nextInt() % 60));
			Date tranTime = cal.getTime();
			try {
				PCPSUtil.Log("subaccno:" + sd.toString());
				accountBusinessImpl.generateAccDetail(issueCompanyNo, subaccno,
						sd, tranTime);
			} catch (Exception e) {
				PCPSUtil.Log("ERROR:" + subaccno, e);
			}
		}
	}
}
